package com.lagou.cl.utils;

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public class JavaPackageFileUtil {

	/**
	 * 获得包下面的所有的class
	 *
	 * @param packageName 所扫描的包的路径
	 * @return List 包含packageName包下的所有class的实例
	 */

	public static List<Class<?>> getClassFromPackage(String packageName) {

		List<Class<?>> clazzs = new ArrayList<>();

		// 是否循环搜索子包
		boolean recursive = true;

		// 包名对应的路径名称
		String packageDirName = packageName.replace('.', '/');
		Enumeration<URL> dirs;

		try {
			dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
			while (dirs.hasMoreElements()) {

				URL url = dirs.nextElement();
				//获取该URL的协议
				String protocol = url.getProtocol();
				if ("file".equals(protocol)) {
					String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
					findClassInPackageByFile(packageName, filePath, recursive, clazzs);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return clazzs;
	}

	/**
	 * 在package对应的路径下找到所有的class
	 *
	 * @param packageName 包的路径
	 * @param filePath    文件路径
	 * @param recursive   是否循环搜索子包
	 * @param clazzs      返回的class的实例集合
	 */
	private static void findClassInPackageByFile(String packageName, String filePath, final boolean recursive, List<Class<?>> clazzs) {
		File dir = new File(filePath);
		if (!dir.exists() || !dir.isDirectory()) {
			return;
		}
		// 在给定的目录下找到所有的文件，并且进行条件过滤
		File[] dirFiles = dir.listFiles(new FileFilter() {

			@Override
			public boolean accept(File file) {
				boolean acceptDir = recursive && file.isDirectory();// 接受dir目录
				boolean acceptClass = file.getName().endsWith("class");// 接受class文件
				return acceptDir || acceptClass;
			}
		});

		for (File file : dirFiles) {
			if (file.isDirectory()) {
				findClassInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, clazzs);
			} else {
				String className = file.getName().substring(0, file.getName().length() - 6);
				try {
					clazzs.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}


	public static void main(String[] args) {

		List<Class<?>> classList = JavaPackageFileUtil.getClassFromPackage("com.lagou.cl");
		for (Class<?> aClass : classList) {
			System.out.println(aClass);
		}
	}
}
